package com.huawang.mdesign.model.service.inter;

import com.huawang.business.dto.graph.ModelInfo;
import com.huawang.business.dto.project.Project;
import com.huawang.business.service.model.base.ElementModelInfoService;
import com.huawang.business.service.model.base.ModelManagerConfig;
import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.business.service.model.core.ModelPropertyInfoService;
import com.huawang.business.service.model.core.project.ProjectManager;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.semantics.entity.queryResult.MofResultContainer;
import com.huawang.core.semantics.entity.script.ElementType;
import com.huawang.mdesign.model.service.util.LogUtil;
import com.huawang.mdesign.model.service.vo.RowElementTypeVo;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Primary
public class ElementTypeService {

    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private ModelManagerConfig managerConfig;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private ProjectManager projectManager;

    @Autowired
    private ElementModelInfoService elementModelInfoService;

    /**
     * 查询所有定义的模型类型
     *
     * @param projectId
     * @param metaClassInstances
     * @param stereotypes
     * @return
     */
    @NotNull
    public RowElementTypeVo queryAllElementType(@NotNull final String projectId,
                                                final List<MetaClassInstance> metaClassInstances,
                                                final List<MetaClassInstance> stereotypes) {
        RowElementTypeVo rowElementTypeVo = new RowElementTypeVo();
        List<ElementType> elementTypesOfMetaClass = getMetaClassElementTypes(projectId, metaClassInstances);
        rowElementTypeVo.setMetaClasses(elementTypesOfMetaClass);
        //自定义stereotype
        List<ElementType> elementTypesOfStereotype = getCustomizationElementTypes(projectId, stereotypes);
        rowElementTypeVo.setStereotypes(elementTypesOfStereotype);
        return rowElementTypeVo;
    }

    @NotNull
    private List<ElementType> getMetaClassElementTypes(@NotNull final String projectId,
                                                       List<MetaClassInstance> metaClassInstances) {
        if (CollectionUtils.isEmpty(metaClassInstances)) {
            return new ArrayList<>();
        }
        List<ElementType> elementTypesOfMetaClass = new ArrayList<>();
        List<MetaClassInstance> absentInfoList = new ArrayList<>();
        metaClassInstances.forEach(model -> {
            ModelInfo info = managerConfig.getModelInfoConfig().get(model.getId());
            if (Objects.nonNull(info)) {
                ElementType elementType = makeElementType(model, info);
                elementTypesOfMetaClass.add(elementType);
            } else {
                absentInfoList.add(model);
            }
        });

        final MofResultContainer container = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(absentInfoList,
                UMLDefinitionConstants.NamedElement_name));
        String defaultMetaClassIcon = "statics/images/sysml/Metaclass.svg";
        absentInfoList.forEach(model -> {
            ElementType elementType = new ElementType();
            String id = model.getId();
            elementType.setIcon(defaultMetaClassIcon);
            final String name = container.queryStringProperty(id, UMLDefinitionConstants.NamedElement_name);
            elementType.setName(name);
            elementType.setValue(id);
            elementType.setEnName(name);
            elementTypesOfMetaClass.add(elementType);
        });
        return elementTypesOfMetaClass;
    }

    @NotNull
    public List<ElementType> getCustomizationElementTypes(@NotNull final String projectId,
                                                          List<MetaClassInstance> stereotypes) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, stereotypes: {}", projectId, stereotypes);
        if (CollectionUtils.isEmpty(stereotypes)) {
            return new ArrayList<>();
        }
        List<MetaClassInstance> customizationStereotype = new ArrayList<>();
        List<ElementType> elementTypesOfStereotype = new ArrayList<>();
        Project project = projectManager.getValidProject(projectId);
        stereotypes.forEach(stereotype -> {
            ModelInfo info = managerConfig.getModelInfoConfig().get(
                    elementModelInfoService.getModelInfoKeyByStereotypeId(stereotype.getId()));
            if (Objects.nonNull(info)) {
                if (CollectionUtils.isEmpty(info.getSpecifications()) || info.getSpecifications().contains(project.getProjectSpecification())) {
                    ElementType elementType = makeElementType(stereotype, info);
                    elementTypesOfStereotype.add(elementType);
                }
            } else {
                customizationStereotype.add(stereotype);
            }
        });
        List<ElementType> customizationElementTypes = new ArrayList<>();
        modelPropertyInfoService.createModelPropertyInfoAndTypeList(projectId, customizationStereotype,
                        Stream.of(UMLDefinitionConstants.Element_appliedStereotype, UMLDefinitionConstants.NamedElement_name)
                                .collect(Collectors.toList()))
                .forEach(model -> {
                    ElementType elementType = new ElementType();
                    elementType.setIcon(managerConfig.getModelInfoConfig().get(UMLDefinitionConstants.Stereotype).getIcon());
                    elementType.setName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                    elementType.setEnName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                    elementType.setValue(model.getInstance().getId());
                    customizationElementTypes.add(elementType);
                });
        elementTypesOfStereotype.addAll(customizationElementTypes);
        return elementTypesOfStereotype;
    }

    @NotNull
    private static ElementType makeElementType(MetaClassInstance model, ModelInfo info) {
        LogUtil.printSerializeOnlineLogs("model: {}, info: {}", model, info);
        ElementType elementType = new ElementType();
        String icon = info.getIcon();
        String name = info.getCnName();
        String id = model.getId();
        elementType.setIcon(icon);
        elementType.setName(name);
        elementType.setValue(id);
        elementType.setEnName(info.getEnName());
        return elementType;
    }

}
